package com.gitee.apanlh.util.algorithm.digest;

import com.gitee.apanlh.util.base.Eq;
import com.gitee.apanlh.util.encode.Base64Utils;
import com.gitee.apanlh.util.encode.HexUtils;
import com.gitee.apanlh.util.io.FileIOUtils;
import com.gitee.apanlh.util.valid.Assert;

import java.io.File;

/**
 * 	摘要算法抽象类
 * 	<br>默认实现基本功能
 * 	<br>继承时需要自定义实现{@link DigestAbstract#hash(byte[])}方法
 * 	
 * 	@author Pan
 * 	@see	JdkDigestAbstract
 * 	@see    CustomDigestAbstract
 */
public abstract class DigestAbstract implements Digest, DigestVerify {
	
	/**	
	 * 	计算hash摘要
	 * 	<br>用于子类中实现指定摘要算法
	 * 	<br>比如SM3中自定义hash算法 例如:{@link SM3#hash(byte[] content)}
	 * 	
	 * 	@author Pan
	 * 	@param 	content				内容
	 * 	@return	byte[]				摘要后的内容
	 */
	public abstract byte[] hash(byte[] content);
	
	@Override
	public byte[] digest(byte[] content) {
		return hash(content);
	}
	
	@Override
	public byte[] digest(String content) {
		Assert.isNotEmpty(content);
		return hash(content.getBytes());
	}
	
	@Override
	public String digestToHex(byte[] content) {
		return HexUtils.encode(hash(content));
	}

	@Override
	public String digestToHex(byte[] content, boolean toLowerCase) {
		return HexUtils.encode(hash(content), toLowerCase);
	}

	@Override
	public String digestToHex(String content) {
		Assert.isNotEmpty(content);
		return digestToHex(content.getBytes());
	}

	@Override
	public String digestToHex(String content, boolean toLowerCase) {
		Assert.isNotEmpty(content);
		return digestToHex(content.getBytes(), toLowerCase);
	}

	@Override
	public byte[] digestToBase64(byte[] content) {
		return Base64Utils.encode(hash(content));
	}

	@Override
	public byte[] digestToBase64(String content) {
		Assert.isNotEmpty(content);
		return Base64Utils.encode(hash(content.getBytes()));
	}

	@Override
	public String digestToBase64Str(byte[] content) {
		return Base64Utils.encodeToStr(hash(content));
	}
	
	@Override
	public String digestToBase64Str(String content) {
		Assert.isNotEmpty(content);
		return Base64Utils.encodeToStr(hash(content.getBytes()));
	}
	
	@Override
	public boolean verify(byte[] plaintextContent, byte[] digestContent) {
		if (plaintextContent == null || digestContent == null) {
			return false;
		}
		return Eq.array(digest(plaintextContent), digestContent);
	}

	@Override
	public boolean verify(File file, File file2) {
		return Eq.array(hash(FileIOUtils.read(file)), hash(FileIOUtils.read(file2)));
	}
	
	@Override
	public boolean verifyBase64(byte[] plaintextContent, byte[] digestContent) {
		if (plaintextContent == null || digestContent == null) {
			return false;
		}
		return Eq.array(digestToBase64(plaintextContent), digestContent);
	}

	@Override
	public boolean verifyBase64(byte[] plaintextContent, String digestContent) {
		if (digestContent == null) {
			return false;
		}
		return digestToBase64Str(plaintextContent).equalsIgnoreCase(digestContent);
	}

	@Override
	public boolean verifyBase64(String plaintextContent, String digestContent) {
		if (digestContent == null) {
			return false;
		}
		return digestToBase64Str(plaintextContent).equalsIgnoreCase(digestContent);
	}

	@Override
	public boolean verifyBase64(File file, String digestContent) {
		if (digestContent == null) {
			return false;
		}
		return digestToBase64Str(FileIOUtils.read(file)).equalsIgnoreCase(digestContent);
	}
	
	@Override
	public boolean verifyHex(byte[] plaintextContent, String digestContent) {
		if (plaintextContent == null || digestContent == null) {
			return false;
		}
		return Eq.array(digestToHex(plaintextContent).getBytes(), digestContent.getBytes());
	}
	
	@Override
	public boolean verifyHex(File file, String digestContent) {
		if (digestContent == null) {
			return false;
		}
		return digestToHex(FileIOUtils.read(file)).equalsIgnoreCase(digestContent);
	}
	
	@Override
	public boolean verifyHex(String plaintextContent, String digestContent) {
		if (digestContent == null) {
			return false;
		}
		return digestToHex(plaintextContent).equalsIgnoreCase(digestContent);
	}
}
